#pragma once
#include <iostream>
#include <vector>
#include <assert.h>
using namespace std;

namespace xyl
{
    template <class T>
    class vector
    {
    public:
        typedef T *iterator;
        typedef const T *const_iterator;

        vector()
            : _start(nullptr),
              _finish(nullptr),
              _end_of_storage(nullptr)
        {
        }

        iterator begin()
        {
            return _start;
        }
        const_iterator begin() const
        {
            return _start;
        }

        iterator end()
        {
            return _finish;
        }
        const_iterator end() const
        {
            return _finish;
        }

        size_t size() const
        {
            return _finish - _start;
        }

        size_t capacity() const
        {
            return _end_of_storage - _start;
        }

        bool empty() const
        {
            return _start == _finish;
        }

        void reserve(size_t n) // n表示新空间大小，即新的_end_of_storage
        {
            if (n > capacity())
            {
                T *tmp = new T[n];
                size_t sz = size();
                if (_start != nullptr)
                {
                    memcpy(tmp, _start, sizeof(T) * sz);
                    delete[] _start;
                }

                _start = tmp;
                _finish = _start + sz;
                _end_of_storage = _start + n;
            }
        }

        iterator insert(iterator pos, const T &val)
        {
            assert(pos >= _start && pos <= _finish);
            // 扩容
            if (_finish == _end_of_storage)
            {
                size_t gap = pos - _start;
                reserve(capacity() == 0 ? 4 : capacity() * 2);
                pos = _start + gap;
            }
            iterator end = _finish;
            while (pos < end)
            {
                *end = *(end - 1);
                --end;
            }
            *pos = val;
            ++_finish;
            return pos;
        }

        iterator erase(iterator pos)
        {
            assert(pos >= _start && pos < _finish);
            iterator tmp = pos;
            while (tmp < _finish - 1)
            {
                *tmp = *(tmp + 1);
                ++tmp;
            }
            --_finish;
            return pos;
        }

        T &operator[](size_t pos)
        {
            assert(pos >= 0 && pos < size());
            return *(_start + pos);
        }

        T &operator[](size_t pos) const
        {
            assert(pos >= 0 && pos < size());
            return *(_start + pos);
        }

    private:
        iterator _start;
        iterator _finish;
        iterator _end_of_storage;
    };

    void test_1()
    {
        vector<int> v1;
        for (int i = 0; i < 16; ++i)
        {
            v1.insert(v1.end(), i);
        }

        for (auto i : v1)
        {
            cout << i << ' ';
        }
        cout << endl;

        for (int i = 0; i < 15; ++i)
        {
            v1.erase(v1.end() - 1);
        }
        for (auto i : v1)
        {
            cout << i << ' ';
        }
        cout << endl;
    }
}